package com.mbv5;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.decorators.LoggingCache;
import org.apache.ibatis.cache.decorators.LruCache;
import org.apache.ibatis.cache.decorators.SerializedCache;
import org.apache.ibatis.cache.decorators.SynchronizedCache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.jdbc.JdbcTransaction;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.junit.Test;

import static com.mbv5.MybatisDemo.sqlSession;

/**
 * Created by qiao on 2017/1/3.
 */
public class SimpleMybatis {

    @Test
    public void test() throws IOException, SQLException {
        final Configuration config = new Configuration();
        config.setCacheEnabled(true);
        config.setLazyLoadingEnabled(false);
        config.setAggressiveLazyLoading(true);

        //可以配置拦截器
//        configuration.addInterceptor();

        //创建DataSource
        Properties props = Resources.getResourceAsProperties("db.properties");
        UnpooledDataSource dataSource=  new UnpooledDataSource();
        dataSource.setDriver(props.getProperty("driver"));
        dataSource.setUrl(props.getProperty("url"));
        dataSource.setUsername(props.getProperty("username"));
        dataSource.setPassword(props.getProperty("password"));

        //创建执行Executor
        Transaction transaction = new JdbcTransaction(dataSource,null,false);

        //config.newExecutor会将符合条件的拦截器添加到Executor代理链上
        final Executor executor = config.newExecutor(transaction);

        //cache是一个多层代理 装饰模式的缓存对象,通过一级级代理使得一个简单缓存
        //拥有cache
        final Cache countryCache =  new SynchronizedCache(new SerializedCache(new LoggingCache(new LruCache(new PerpetualCache("country_cache")))));

        //类型处理注册器
        //自已写TypeHandler的时候,可以参考该注册器中的已经存在的大量实现
        final TypeHandlerRegistry registry = config.getTypeHandlerRegistry();

        //================== 下面的步骤相当于解析XML或者解析接口注解方法生成ms =====================
        StaticSqlSource sqlSource = new StaticSqlSource(config,"select * from s_apply where id = #{id}");
        List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
        parameterMappings.add(new ParameterMapping.Builder(config,"id",registry.getTypeHandler(int.class)).build());
        ParameterMap.Builder paramBuilder = new ParameterMap.Builder(config, "defaultParameterMap", HashMap.class, parameterMappings);
        //创建ms
        MappedStatement.Builder msBuilder = new MappedStatement.Builder(config,"com.mbv5.dao.Apply.list",sqlSource, SqlCommandType.SELECT);
        msBuilder.parameterMap(paramBuilder.build());

        ResultMap resultMap =  new ResultMap.Builder(config,"defaultResultMap",HashMap.class,new ArrayList<ResultMapping>(){
            {
                add(new ResultMapping.Builder(config,"id","id",int.class).build());
            }
        }).build();

        List<ResultMap> resultMaps = new ArrayList<ResultMap>();
        resultMaps.add(resultMap);
        //设置返回的值的resultMap与resultType
        msBuilder.resultMaps(resultMaps);
        //设置缓存
        msBuilder.cache(countryCache);
        MappedStatement ms = msBuilder.build();
        List<Map<String,Object>> rs = executor.query(ms,1, RowBounds.DEFAULT,Executor.NO_RESULT_HANDLER);
        System.out.println(rs);

        //第二种
//        config.addMappedStatement(ms);
//        SqlSession sqlSession  = new DefaultSqlSession(config,executor,false);
//        List<Map<String,Object>> rs2 = sqlSession.selectList("list");
        sqlSession.close();
        System.out.println("over");
    }
}
